home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / child.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  4.7 KB  |  211 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: child.c,v 5.2 1993/01/23 02:04:02 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <syslog.h>
  13.  
  14. #include "str.h"
  15.  
  16. #include "options.h"
  17.  
  18. #include "attr.h"
  19. #include "server.h"
  20. #include "state.h"
  21.  
  22. char *inet_ntoa() ;
  23.  
  24. void msg() ;
  25. void msg_suspend() ;
  26. void msg_resume() ;
  27.  
  28. /*
  29.  * This function is invoked in a forked process to run a server. 
  30.  * If the service is internal the appropriate function is invoked
  31.  * otherwise the server is exec'ed.
  32.  * This functions also logs the remote user id if appropriate
  33.  */
  34. void child_process( serp )
  35.     register struct server *serp ;
  36. {
  37.     register struct service_config *scp = CONF( SERVER_SERVICE( serp ) ) ;
  38.     void signal_default_state() ;
  39.     void rename_process() ;
  40.     void set_credentials() ;
  41.     void exec_server() ;
  42.     void log_remote_user() ;
  43.  
  44. #ifdef DEBUG_SERVER
  45.     if ( debug.on )
  46.     {
  47.         msg( LOG_DEBUG, "child_process", "Process %d is sleeping", getpid() ) ;
  48.         sleep( 10 ) ;
  49.     }
  50. #endif
  51.  
  52.     if ( ! IS_INTERCEPTED( scp ) )
  53.     {
  54.         set_credentials( scp ) ;
  55.         signal_default_state() ;
  56.     }
  57.  
  58.     if ( serp->log_remote_user )
  59.         log_remote_user( serp ) ;
  60.  
  61.     if ( ! IS_INTERNAL( scp ) )
  62.         exec_server( serp ) ;
  63.     else
  64.     {
  65.         char name[ 180 ] ;
  66.  
  67.         /*
  68.          * NOTE: We don't bother to disassociate from the controlling terminal
  69.          *            (we have a controlling terminal only if debug.on is TRUE)
  70.          *
  71.          * Also, for interceptor processes, we give them the name:
  72.          *                interceptor service-id
  73.          */
  74.         if ( IS_INTERCEPTED( scp ) )
  75.             strx_print( INT_NULL, name, sizeof( name ),
  76.                                         "%s %s interceptor", program_name, scp->id ) ;
  77.         else
  78.         {
  79.             int namelen = sizeof( name ) - 1 ;        /* leave space for the NUL */
  80.             struct sockaddr_in *sinp = conn_address( SERVER_CONNECTION( serp ) ) ;
  81.             int len = strx_nprint( name, namelen,
  82.                                             "(%s service) %s", program_name, scp->id ) ;
  83.             
  84.             if ( ACCEPTS_CONNECTIONS( scp ) && sinp != SOCKADDRIN_NULL )
  85.                 strx_print( INT_NULL, &name[ len ], namelen - len,
  86.                                                     " %s", inet_ntoa( sinp->sin_addr ) ) ;
  87.         }
  88.         rename_process( name ) ;
  89.         (*SERVER_SERVICE( serp )->builtin->function)( serp ) ;
  90.     }
  91.     _exit( 0 ) ;
  92.     /* NOTREACHED */
  93. }
  94.  
  95.  
  96. PRIVATE void exec_server( serp )
  97.     struct server *serp ;
  98. {
  99.     struct service_config *scp = CONF( SERVER_SERVICE( serp ) ) ;
  100.     int fd ;
  101.     int descriptor = SERVER_FD( serp ) ;
  102.     char *func = "exec_server" ;
  103.     void no_control_tty() ;
  104.  
  105.     if ( debug.on )
  106.         msg( LOG_DEBUG, func, "duping %d", descriptor ) ;
  107.  
  108.     for ( fd = 0 ; fd <= 2 ; fd++ )
  109.         if ( dup2( descriptor, fd ) == -1 )
  110.         {
  111.             msg( LOG_ERR, func,
  112.                     "dup2( %d, %d ) failed: %m", descriptor, fd ) ;
  113.             _exit( 1 ) ;
  114.         }
  115.  
  116.     (void) close( descriptor ) ;
  117.  
  118.     if ( debug.on )
  119.     {
  120.         msg( LOG_DEBUG, func,
  121.                 "exec( %s ). no control terminal", scp->server ) ;
  122.         no_control_tty() ;
  123.     }
  124.  
  125. #ifdef RLIMIT_NOFILE
  126.     {
  127.         struct rlimit rl ;
  128.  
  129.         rl.rlim_cur = ps.ros.orig_max_descriptors ;
  130.         rl.rlim_max = ps.ros.max_descriptors ;
  131.         (void) setrlimit( RLIMIT_NOFILE, &rl ) ;
  132.     }
  133. #endif
  134.  
  135.     msg_suspend() ;
  136.  
  137.     (void) execve( scp->server, scp->server_argv, 
  138.                                                     env_getvars( ENV( scp )->env ) ) ;
  139.  
  140.     /*
  141.      * The exec failed. Log the error and exit.
  142.      */
  143.     msg_resume() ;
  144.     msg( LOG_ERR, func, "execv( %s ) failed: %m", scp->server ) ;
  145.     _exit( 0 ) ;
  146. }
  147.  
  148.  
  149. /*
  150.  * Rename this process by changing the ps.ros.Argv vector
  151.  * Try to put the name of the service in ps.ros.Argv[0], Argv[1]
  152.  * until either the service name is exhausted or we run out
  153.  * of ps.ros.Argv's. 
  154.  * The rest of ps.ros.Argv is cleared to spaces
  155.  */
  156. PRIVATE void rename_process( name )
  157.     char *name ;
  158. {
  159.     register char *from = name ;
  160.     register char *to = ps.ros.Argv[ 0 ] ;
  161.     register int index = 1 ;
  162.  
  163.     while ( *from != NUL )
  164.     {
  165.         if ( *to != NUL )
  166.             *to++ = *from++ ;
  167.         else
  168.             if ( index < ps.ros.Argc )
  169.                 to = ps.ros.Argv[ index++ ] ;
  170.             else
  171.                 break ;
  172.     }
  173.     str_fill( to, ' ' ) ;
  174.     while ( index < ps.ros.Argc )
  175.         str_fill( ps.ros.Argv[ index++ ], ' ' ) ;
  176. }
  177.  
  178.  
  179. PRIVATE void set_credentials( scp )
  180.     register struct service_config *scp ;
  181. {
  182.     char *func = "set_credentials" ;
  183.  
  184.     if ( SPECIFIED( scp, A_GROUP ) || SPECIFIED( scp, A_USER ) )
  185.         if ( ps.ros.is_superuser )
  186.         {
  187.             int gid = SPECIFIED( scp, A_GROUP ) ? scp->gid : scp->user_gid ;
  188.  
  189.             if ( setgid( gid ) == -1 )
  190.             {
  191.                 msg( LOG_ERR, func, "setgid failed: %m" ) ;
  192.                 _exit( 1 ) ;
  193.             }
  194.         }
  195.         else
  196.             msg( LOG_WARNING, func, "can't change gid; not superuser" ) ;
  197.  
  198.     if ( SPECIFIED( scp, A_USER ) )
  199.         if ( ps.ros.is_superuser )
  200.         {
  201.             if ( setuid( scp->uid ) == -1 )
  202.             {
  203.                 msg( LOG_ERR, func, "setuid failed: %m" ) ;
  204.                 _exit( 1 ) ;
  205.             }
  206.         }
  207.         else
  208.             msg( LOG_WARNING, func, "can't change uid; not superuser" ) ;
  209. }
  210.  
  211.